#pragma once 
#include<vector>
#include<string>
#include <cstdint>
#include <bit>


// === 跨平台字节序检测 ===
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    #define IS_LITTLE_ENDIAN true
#elif defined(_WIN32) || defined(_MSC_VER)
    #define IS_LITTLE_ENDIAN true   // Windows 始终为小端
#else
    #define IS_LITTLE_ENDIAN false
#endif




namespace tmms
{
    namespace network
    {
        static const size_t kCheapPrepend = 8;   // 初始预留的prependable空间大小
        static const size_t kInitialSize = 1024; // Buffer初始大小
        class MsgBuffer 
        {
        public:
            static constexpr char kCRLF[] = "\r\n"; 
            MsgBuffer(size_t initialSize = kInitialSize);
            ~MsgBuffer();

            size_t readableBytes() const;  /* 返回 readable 空间大小 */
            size_t writableBytes() const;/* 返回 writeable 空间大小 */
            size_t prependableBytes() const;/* 返回 prependable 空间大小 */
            const char* peek() const;/* readIndex 对应元素地址 */
            
            char* beginWrite();/* 返回待写入数据的地址, 即writable空间首地址 */
            const char* beginWrite() const;

            void hasWritten(size_t len); /* 将writerIndex_往后移动len byte, 需要确保writable空间足够大 */
            void unwrite(size_t len);   /* 将writerIndex_往前移动len byte, 需要确保readable空间足够大 */

            //retrieve系列函数从readable空间取走数据，只关心移动readableIndex_，改变readable空间大小
            void retrieve(size_t len); //这里取走数据，是个移动readerindex
            void retrieveUntil(const char* end);
            void retrieveInt64();
            void retrieveInt32();
            void retrieveInt16();
            void retrieveInt8();
            void retrieveAll();
            std::string retrieveAllAsString();  /* 从readable空间取走所有数据, 转换为字符串返回 */ 
            std::string retrieveAsString(size_t len);/* 从readable空间头部取走长度len byte的数据, 转换为字符串返回 */
            //readInt系列函数从readable空间读取指定长度（类型）的数据，不仅从readable空间读取数据，还会利用相应的retrieve函数把数据从中取走，导致readable空间变小。
            int64_t readInt64();
            int32_t readInt32();
            int16_t readInt16();
            int8_t readInt8();
            //peek系列函数只从readable空间头部（peek()）读取数据，而不取走数据，不会导致readable空间变化。
            int64_t peekInt64() const;
            int32_t peekInt32() const;
            int16_t peekInt16() const;
            int8_t peekInt8() const;
            //prepend系列函数将预置指定长度数据到prependable空间，但不会改变prependable空间大小。
            void prependInt64(int64_t x);
            void prependInt32(int32_t x);
            void prependInt16(int16_t x);
            void prependInt8(int8_t x);
            void prepend(const void* data, size_t len);


            //内部缓冲区操作
            void shrink(size_t reserve); /* 收缩缓冲区空间, 将缓冲区中数据拷贝到新缓冲区, 确保writable空间最终大小为reserve */ 
            size_t internalCapacity() const; /* 返回buffer_的容量capacity() */
            void makeSpace(size_t len);/* writable空间不足以写入len byte数据时,
            * 1)如果writable空间 + prependable空间不足以存放数据, 就resize 申请新的更大的内部缓冲区buffer_
            * 2)如果足以存放数据, 就将prependable多余空间腾挪出来, 合并到writable空间 */

            //readFd从指定fd读取数据,从fd读取数据到内部缓冲区
            ssize_t readFd(int fd, int* savedErrno);

            //readable空间特定字符串查找
            const char* findCRLF() const;
            const char* findCRLF(const char* start) const;
            const char* findEOL() const;
            const char* findEOL(const char* start) const;
  
        private:
            std::vector<char> buffer_;// 存储数据的线性缓冲区, 大小可变
            size_t readerIndex_;//可读数据首地址, i.e. readable空间首地址
            size_t writerIndex_;// 可写数据首地址, i.e. writable空间首地址
          
            char* begin() {//常量性重载​// Buffer buf;    // 非 const 对象​ //buf.begin()[0] = 'a'; // ✅ 调用非 const 版本，允许修改
                return &*buffer_.begin();
            }
            const char* begin() const { // const Buffer cbuf;   // const 对象 // const char* p = cbuf.begin(); // ✅ 合法，只读访问
                return &*buffer_.begin();
            }

            int64_t networkToHost64(int64_t net64) const
            {  // 参数类型和返回类型都使用 int64_t
                // 使用带符号类型直接操作
                if constexpr (IS_LITTLE_ENDIAN) {
                    // 小端系统执行字节翻转
                    int64_t result = 0;
                    result |= (net64 & 0x00000000000000FFLL) << 56;
                    result |= (net64 & 0x000000000000FF00LL) << 40;
                    result |= (net64 & 0x0000000000FF0000LL) << 24;
                    result |= (net64 & 0x00000000FF000000LL) << 8;
                    result |= (net64 & 0x0000FF0000000000LL) >> 8;
                    result |= (net64 & 0x00FF000000000000LL) >> 24;
                    result |= (net64 & 0xFF00000000000000LL) >> 56;
                    return result;
                } else {
                    return net64;  // 大端系统直接返回
                }
            }

            int32_t networkToHost32(int32_t net32) const 
            {
                if constexpr (IS_LITTLE_ENDIAN) {
                    // 小端系统需要字节交换
                    return static_cast<int32_t>(
                        ((net32 & 0x000000FF) << 24) |
                        ((net32 & 0x0000FF00) <<  8) |
                        ((net32 & 0x00FF0000) >>  8) |
                        ((net32 & 0xFF000000) >> 24)
                    );
                } else {
                    return net32;  // 大端系统直接返回
                }
            }


            // 16位网络序到主机序转换
            int16_t networkToHost16(int16_t net16) const 
            {
                if constexpr (IS_LITTLE_ENDIAN) {
                    // 小端系统需要字节交换
                    return static_cast<int16_t>(
                    ((net16 & 0x00FF) << 8) |
                    ((net16 & 0xFF00) >> 8)
                    );
                } else {
                    return net16;  // 大端系统直接返回
                }
            }


            int16_t hostToNetwork16(int16_t host16) const {
                if constexpr (IS_LITTLE_ENDIAN) {
                    return static_cast<int16_t>(
                        ((host16 & 0x00FF) << 8) | ((host16 & 0xFF00) >> 8)
                    );
                } else {
                    return host16;
                }
            }
            
            int32_t hostToNetwork32(int32_t host32) const {
                if constexpr (IS_LITTLE_ENDIAN) {
                    return static_cast<int32_t>(
                        ((host32 & 0x000000FF) << 24) |
                        ((host32 & 0x0000FF00) << 8)  |
                        ((host32 & 0x00FF0000) >> 8)  |
                        ((host32 & 0xFF000000) >> 24)
                    );
                } else {
                    return host32;
                }
            }

            int64_t hostToNetwork64(int64_t host64) const {
                if constexpr (IS_LITTLE_ENDIAN) {
                    int64_t result = 0;
                    result |= (host64 & 0x00000000000000FFLL) << 56;
                    result |= (host64 & 0x000000000000FF00LL) << 40;
                    result |= (host64 & 0x0000000000FF0000LL) << 24;
                    result |= (host64 & 0x00000000FF000000LL) << 8;
                    result |= (host64 & 0x0000FF0000000000LL) >> 8;
                    result |= (host64 & 0x00FF000000000000LL) >> 24;
                    result |= (host64 & 0xFF00000000000000LL) >> 56;
                    return result;
                } else {
                    return host64;
                }
            }

            void append(const void* data, size_t len) {
                // 1. 确保有足够的可写空间
                if (len > writableBytes()) {
                    makeSpace(len);
                }
                // 2. 拷贝数据到可写区域
                std::copy(static_cast<const char*>(data), 
                        static_cast<const char*>(data) + len, 
                        beginWrite());
                // 3. 更新写索引
                hasWritten(len);
            }

        };
    }

}